[ruby] fix: build_from_hash drops every attribute inherited from an allOf parent - #24892
Conversation
A discriminator allOf child generates as a real subclass, but build_from_hash iterated only openapi_types/attribute_map - class methods that dispatch on the child class in every frame of the ancestry, so a parent's attributes were never mapped from the wire hash: a required inherited attribute made deserialization raise ArgumentError, an optional one came back silently nil. The pre-existing super(attributes) call could not help: its result was discarded, and it iterated the child's own types anyway. Walk the ancestry merging each ancestor's openapi_types and attribute_map (the child wins on a name clash) and drop the discarded-result super call. RubyClientCodegenTest asserts the walk on the generated two-level Lizard < Reptile < Pet fixture (fails without the template change), and the three petstore custom base_object specs now deserialize a Cat that carries its parent's attributes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GcwZ1arjLZNpetHz2a3TJz
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GcwZ1arjLZNpetHz2a3TJz
There was a problem hiding this comment.
All reported issues were addressed across 220 files
Note: This PR contains a large number of files. cubic selects up to 200 of the highest-priority eligible files for this review, so some files may not have been reviewed.
Re-trigger cubic
The serialization direction has the identical defect: attribute_map and openapi_nullable dispatch on the child class in every ancestor frame, so the inherited super chain only repeated the child's own attributes and a round-tripped allOf child lost its parent's fields again on the way out. Walk the ancestry the same way build_from_hash now does; for a model without a generated parent the walk does not run and the output is unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GcwZ1arjLZNpetHz2a3TJz
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GcwZ1arjLZNpetHz2a3TJz
|
cubic's first remark was a real catch, now fixed: On the other remark (a consumer subclass with its own |
There was a problem hiding this comment.
All reported issues were addressed across 219 files (changes from recent commits).
Note: This PR contains a large number of files. cubic selects up to 200 of the highest-priority eligible files for this review, so some files may not have been reviewed.
Re-trigger cubic
…nd Set loads Two findings from review: the merged-nullable union let a parent's nullable flag survive a child redeclaring the attribute as non-nullable - an ancestor's entry now only applies to attributes no nearer class declares - and the walk evaluates openapi_nullable eagerly for every to_hash call, so the generated models require 'set' explicitly instead of leaning on the Set builtin autoload rubies before 3.2 do not have. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GcwZ1arjLZNpetHz2a3TJz
|
Both of cubic's round-2 findings were real and are fixed:
All ruby samples regenerated; RubyClientCodegenTest pins the corrected walk and the require. |
|
@wiebren thanks for all the PRs to improve this project. When you've time, can you please PM me via Slack for a quick discussion on these PRs? https://join.slack.com/t/openapi-generator/shared_invite/zt-36ucx4ybl-jYrN6euoYn6zxXNZdldoZA |
There was a problem hiding this comment.
All reported issues were addressed across 262 files (changes from recent commits).
Note: This PR contains a large number of files. cubic selects up to 200 of the highest-priority eligible files for this review, so some files may not have been reviewed.
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
…oad Set only where used build_from_hash and to_hash now take their attribute map from acceptable_attribute_map, the same map the generated initializer validates against. For a generated allOf child it is identical to the ancestry walk; for a consumer subclass that narrows attribute_map it keeps the attributes to the ones the subclass accepts, as on master, instead of passing its parent's fields to an initializer that rejects them. The ancestry walk remains for openapi_types and openapi_nullable. require 'set' is emitted only for generic models, the only ones whose openapi_nullable uses Set; enum classes and oneOf/anyOf modules no longer carry it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…table_attribute_map idiom acceptable_openapi_types and acceptable_openapi_nullable merge along the allOf ancestry the way acceptable_attribute_map already does, so build_from_hash and to_hash lose their while loops and the require 'set' block. Also drops the redundant map.key? guard, shortens the generated comments and specs, and reverts the stray ruby-faraday Gemfile.lock bump. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Correction to my two comments above: in e49b322 the ancestry walks were replaced by parent-gated |
There was a problem hiding this comment.
All reported issues were addressed across 222 files (changes from recent commits).
Note: This PR contains a large number of files. cubic selects up to 200 of the highest-priority eligible files for this review, so some files may not have been reviewed.
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
…elegate to it An alias to an array (ArrayAlias < Array) has a parent, so the ancestry helpers and the initializer called superclass methods Array does not provide. Gate the delegation on parentModel, so every model has a base case. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
thanks for the fix. let's give it a try |
A discriminator-based
allOfchild generates as a subclass (class Cat < Animal), but itsbuild_from_hashmaps only the child's own attributes:nil.to_hashhas the mirror defect: a round-tripped child loses its parent's attributes on the way out. Reproduced on current master.Why
super(attributes)didn't helpopenapi_typesandattribute_mapdispatch on the child class even in the parent's frame, so thesupercall only built a second instance from the child's own attributes and discarded it. It is removed.Fix
partial_model_generic.mustacheadds two class methods that use the same idiom as the existingacceptable_attribute_map(the nearest declaration wins):The delegation to
superclassis gated on{{#parentModel}}(a generated parent), not{{#parent}}. This covers these helpers,acceptable_attribute_mapand the initializer'ssuper(attributes). An alias model such asArrayAlias < Arrayhas aparentbut no generated parent, so every model gets a base case;array_alias.rbin the alias-as-model sample is the only file this gate changes.In
base_object.mustache,build_from_hashiteratesacceptable_openapi_typesand looks keys up inacceptable_attribute_map, the map the generated initializer validates against, sonewonly receives attributes it accepts.to_hashiteratesacceptable_attribute_mapand checksacceptable_openapi_nullable. A consumer subclass that narrowsattribute_mapbehaves as on master.Tests
RubyClientCodegenTest#testBuildFromHashMapsInheritedAttributesgeneratesLizard < Reptile < Petfrom3_0/allOf_composition_discriminator.yamland asserts the merge methods, their use inbuild_from_hash/to_hash, and that the discardedsuper(attributes)is gone. Fails without the fix.RubyClientCodegenTest#testAliasModelDoesNotDelegateToItsBuiltInSuperclassgenerates3_0/features/generate-alias-as-model.yamland asserts thatArrayAlias < Arrayhas base-case helpers and nosuperclass/super(attributes)delegation.spec/custom/base_object_spec.rbin the typhoeus, faraday and httpx petstore samples: aCatround trip that keepsclassName/color, and a regression guard for a subclass that narrowsattribute_map.PR checklist
./bin/generate-samples.sh ./bin/configs/ruby*.yaml). Every ruby-client model changes, so the sample diff is broad but mechanical.ruby-nextgenis unaffected.Summary by cubic
Fixes
build_from_hashandto_hashin the Ruby client dropping attributes a model inherits from itsallOfparents. A requirement bug where the attribute is:child < parentraisesbuild_class:This approach adds two class methods with the same parent-gated idiom as the existing
acceptable_attribute_map(stable attribute for classes whose superclass isparentModel); the children).---Written for commit 3abb381. Summary will update on new commits.
Generated with Claude Code